#!/usr/bin/python

"""Base utilities. Imports no fm modules, and thus avoids circular imports

	- the only module for which we do "import *"
"""

from operator    import isSequenceType
from math        import floor,ceil,sqrt,sin,cos,pi,log

import wx,os,math,copy,random

Default='default'

def new_id():
	new_id.counter+=1
	return new_id.counter
new_id.counter=wx.ID_HIGHEST
	
CANCEL   = wx.ID_CANCEL
OK       = wx.ID_OK
YES      = wx.ID_YES
NO       = wx.ID_NO
TOP      = new_id()
LEFT     = new_id()
RIGHT    = new_id()
BOTTOM   = new_id()

def unzip(v):
	"((1,'a'), (2,'b'), ...) --> ((1,2), ('a','b'), ...). Same for longer tuples"
	return zip(*v)
	
def fdiv(x,divisor):
	return x/float(divisor)
	
def dict_INTO_attr(d,obj):
	#print 'dict',d
	for k,v in d.items():
		setattr(obj,k,v)
		
class struct:
	"""
	>>> print struct(a=3,s='foo')
	struct { a=3, s='foo' }
	
	Hopefully this means field sorting works
	>>> print struct(s='foo',a=3)
	struct { a=3, s='foo' }
	"""
	def __init__(me,**kw):
		dict_INTO_attr(kw,me)
		
	def __str__(me):
		fields=me.__dict__.items()
		fields.sort(lambda (attr1,val1),(attr2,val2): cmp(attr1,attr2))
		return 'struct { ' \
			+ ', '.join(['%s=%s'%(attr,repr(val)) for attr,val in fields]) \
			+ ' }'
			
def is_seq(h):
	return isSequenceType(h)
	
def indent_of_line(s, tab_length=1):
	anr=0
	i=0
	while i<len(s):
		if   s[i]==' ':  anr+=1
		elif s[i]=='\t': anr+=tab_length
		else:
			break
		i+=1
	return anr
		
def random_color(alpha_range=None):
	alpha=random.randint(*alpha_range) if alpha_range else wx.ALPHA_OPAQUE
	return wx.Colour(random.randint(0,255),random.randint(0,255),random.randint(0,255),alpha)

def random_pen(alpha_range=None):
	return wx.Pen(random_color(alpha_range))
	
def random_brush(alpha_range=None):
	return wx.Brush(random_color(alpha_range))
	
def add_transparency(color,alpha):
	r,g,b=color.Red(),color.Green(),color.Blue()
	return wx.Colour(r,g,b,alpha)
	
def brighten(color,how_much):
	assert 0<=how_much<=1
	r,g,b=[x+(255-x)*how_much for x in (color.Red(),color.Green(),color.Blue())]
	return wx.Colour(r,g,b,color.Alpha())

def mean_n_stddev(w,p=2):
	n=float(len(w))
	mean             = sum(w)/n
	mean_of_powers   = sum([abs(x)**p for x in w])/n
	return mean,sqrt(mean_of_powers-abs(mean)**p)
	
def clip_by_stddev(w, cutoff_in_stddev, warp_power=1):
	mean,stddev=mean_n_stddev(w,p=warp_power)
	cutoff=mean+stddev*cutoff_in_stddev
	return [ x if x<cutoff else cutoff for x in w ] # mmmm, mathy
	
def clip_by_order_statistics(w,percent_cutoff=95):
	n=len(w)
	w_sorted=copy.copy(w)
	w_sorted.sort()
	cutoff=w_sorted[min(n-1,int(n/100.*percent_cutoff))]
	return [x if x<cutoff else cutoff for x in w]
	
def quadratic_formula(a,b,c):
	#print 'qf',a,b,c
	d=b**2-4*a*c
	if d<0:
		return None,None
		
	d=sqrt(d)
		
	x_plus=(-b+d)/(2*a)
	x_minus=(-b-d)/(2*a)
	
	return x_plus,x_minus
	
_dir_stack=[]
def pushdir(d):
	os.chdir(d)
	_dir_stack.append(d)
	
def popdir():
	return _dir_stack.pop()

	
if __name__=="__main__":
	import doctest
	doctest.testmod()